home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / shells / tcshsrc.zoo / tcsh / tc.bind.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-25  |  19.9 KB  |  944 lines

  1. /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/tc.bind.c,v 3.1 1991/07/15 19:37:24 christos Exp $ */
  2. /*
  3.  * tc.bind.c: Key binding functions
  4.  */
  5. /*-
  6.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *    This product includes software developed by the University of
  20.  *    California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37. #include "config.h"
  38. RCSID("$Id: tc.bind.c,v 3.1 1991/07/15 19:37:24 christos Exp $")
  39.  
  40. #include "sh.h"
  41. #include "ed.h"
  42. #include "ed.defns.h"
  43.  
  44. static    int    str7cmp        __P((char *, char *));
  45. static    int    tocontrol    __P((int));
  46. static    char  *unparsekey    __P((int));
  47. static    KEYCMD getkeycmd    __P((Char **));
  48. static    int    parsekey        __P((Char **));
  49. static    void   printkey        __P((KEYCMD *, Char *));
  50. static    KEYCMD parsecmd        __P((Char *));
  51. static    Char  *parsestring    __P((Char *, Char *));
  52. static    void   print_all_keys    __P((void));
  53. static    void   printkeys    __P((KEYCMD *, int, int));
  54. static    void   bindkey_usage    __P((void));
  55. static    void   list_functions    __P((void));
  56. static    void   pkeys        __P((int, int));
  57.  
  58. extern int MapsAreInited;
  59.  
  60. /* like strcmp, but compairisons are striped to 7 bits
  61.    (due to shell stupidness) */
  62. static int
  63. str7cmp(a, b)
  64.     register char *a, *b;
  65. {
  66.     while ((*a & TRIM) == (*b++ & TRIM))
  67.     if (!*a++)
  68.         return (0);
  69.     b--;
  70.     return ((*a & TRIM) - (*b & TRIM));
  71. }
  72. static int
  73. tocontrol(c)
  74.     int    c;
  75. {
  76.     c &= CHAR;
  77.     if (Islower(c))
  78.     c = Toupper(c);
  79.     else if (c == ' ')
  80.     c = '@';
  81.     if (c == '?')
  82.     c = 0177;
  83.     else
  84.     c &= 037;
  85.     return (c);
  86. }
  87.  
  88. static char *
  89. unparsekey(c)            /* 'c' -> "c", '^C' -> "^" + "C" */
  90.     register int c;
  91. {
  92.     register char *cp;
  93.     static char tmp[10];
  94.  
  95.     cp = tmp;
  96.  
  97.     if (c & 0400) {
  98.     *cp++ = 'A';
  99.     *cp++ = '-';
  100.     c &= 0377;
  101.     }
  102.     if ((c & META) && !(Isprint(c) || Iscntrl(c) && Isprint(c | 0100))) {
  103.     *cp++ = 'M';
  104.     *cp++ = '-';
  105.     c &= ASCII;
  106.     }
  107.     if (Isprint(c)) {
  108.     *cp++ = c;
  109.     *cp = '\0';
  110.     return (tmp);
  111.     }
  112.     else if (c == ' ') {
  113.     (void) strcpy(cp, "Spc");
  114.     return (tmp);
  115.     }
  116.     else if (c == '\n') {
  117.     (void) strcpy(cp, "Lfd");
  118.     return (tmp);
  119.     }
  120.     else if (c == '\r') {
  121.     (void) strcpy(cp, "Ret");
  122.     return (tmp);
  123.     }
  124.     else if (c == '\t') {
  125.     (void) strcpy(cp, "Tab");
  126.     return (tmp);
  127.     }
  128.     else if (c == '\033') {
  129.     (void) strcpy(cp, "Esc");
  130.     return (tmp);
  131.     }
  132.     else if (c == '\177') {
  133.     (void) strcpy(cp, "Del");
  134.     return (tmp);
  135.     }
  136.     else {
  137.     *cp++ = '^';
  138.     if (c == '\177') {
  139.         *cp++ = '?';
  140.     }
  141.     else {
  142.         *cp++ = c | 0100;
  143.     }
  144.     *cp = '\0';
  145.     return (tmp);
  146.     }
  147. }
  148.  
  149. static  KEYCMD
  150. getkeycmd(sp)
  151.     Char  **sp;
  152. {
  153.     register Char *s = *sp;
  154.     register char c;
  155.     register KEYCMD keycmd = F_UNASSIGNED;
  156.     KEYCMD *map;
  157.     int     meta = 0;
  158.     Char   *ret_sp = s;
  159.  
  160.     map = CcKeyMap;
  161.  
  162.     while (*s) {
  163.     if (*s == '^' && s[1]) {
  164.         s++;
  165.         c = tocontrol(*s++);
  166.     }
  167.     else
  168.         c = *s++;
  169.  
  170.     if (*s == '\0')
  171.         break;
  172.  
  173.     switch (map[c | meta]) {
  174.     case F_METANEXT:
  175.         meta = META;
  176.         keycmd = F_METANEXT;
  177.         ret_sp = s;
  178.         break;
  179.  
  180.     case F_XKEY:
  181.         keycmd = F_XKEY;
  182.         ret_sp = s;
  183.         /* FALLTHROUGH */
  184.  
  185.     default:
  186.         *sp = ret_sp;
  187.         return (keycmd);
  188.  
  189.     }
  190.     }
  191.     *sp = ret_sp;
  192.     return (keycmd);
  193. }
  194.  
  195. static int
  196. parsekey(sp)
  197.     Char  **sp;            /* Return position of first unparsed character
  198.                  * for return value -2 (xkeynext) */
  199. {
  200.     register int c, meta = 0, control = 0, ctrlx = 0;
  201.     Char   *s = *sp;
  202.     KEYCMD  keycmd;
  203.  
  204.     if (s == NULL) {
  205.     xprintf("bad key specification -- null string\n");
  206.     return -1;
  207.     }
  208.     if (*s == 0) {
  209.     xprintf("bad key specification -- empty string\n");
  210.     return -1;
  211.     }
  212.  
  213.     (void) strip(s);        /* trim to 7 bits. */
  214.  
  215.     if (s[1] == 0)        /* single char */
  216.     return (s[0] & 0377);
  217.  
  218.     if ((s[0] == 'F' || s[0] == 'f') && s[1] == '-') {
  219.     if (s[2] == 0) {
  220.         xprintf("Bad function-key specification.  Null key not allowed\n");
  221.         return (-1);
  222.     }
  223.     *sp = s + 2;
  224.     return (-2);
  225.     }
  226.  
  227.     if (s[0] == '0' && s[1] == 'x') {    /* if 0xn, then assume number */
  228.     c = 0;
  229.     for (s += 2; *s; s++) {    /* convert to hex; skip the first 0 */
  230.         c *= 16;
  231.         if (!Isxdigit(*s)) {
  232.         xprintf("bad key specification -- malformed hex number\n");
  233.         return -1;    /* error */
  234.         }
  235.         if (Isdigit(*s))
  236.         c += *s - '0';
  237.         else if (*s >= 'a' && *s <= 'f')
  238.         c += *s - 'a' + 0xA;
  239.         else if (*s >= 'F' && *s <= 'F')
  240.         c += *s - 'A' + 0xA;
  241.     }
  242.     }
  243.     else if (s[0] == '0' && Isdigit(s[1])) {    /* if 0n, then assume number */
  244.     c = 0;
  245.     for (s++; *s; s++) {    /* convert to octal; skip the first 0 */
  246.         if (!Isdigit(*s) || *s == '8' || *s == '9') {
  247.         xprintf("bad key specification -- malformed octal number\n");
  248.         return -1;    /* error */
  249.         }
  250.         c = (c * 8) + *s - '0';
  251.     }
  252.     }
  253.     else if (Isdigit(s[0]) && Isdigit(s[1])) {    /* decimal number */
  254.     c = 0;
  255.     for (; *s; s++) {    /* convert to octal; skip the first 0 */
  256.         if (!Isdigit(*s)) {
  257.         xprintf("bad key specification -- malformed decimal number\n");
  258.         return -1;    /* error */
  259.         }
  260.         c = (c * 10) + *s - '0';
  261.     }
  262.     }
  263.     else {
  264.     keycmd = getkeycmd(&s);
  265.  
  266.     if ((s[0] == 'X' || s[0] == 'x') && s[1] == '-') {    /* X- */
  267.         ctrlx++;
  268.         s += 2;
  269.         keycmd = getkeycmd(&s);
  270.     }
  271.     if ((*s == 'm' || *s == 'M') && s[1] == '-') {    /* meta */
  272.         meta++;
  273.         s += 2;
  274.         keycmd = getkeycmd(&s);
  275.     }
  276.     else if (keycmd == F_METANEXT && *s) {    /* meta */
  277.         meta++;
  278.         keycmd = getkeycmd(&s);
  279.     }
  280.     if (*s == '^' && s[1]) {
  281.         control++;
  282.         s++;
  283.         keycmd = getkeycmd(&s);
  284.     }
  285.     else if ((*s == 'c' || *s == 'C') && s[1] == '-') {    /* control */
  286.         control++;
  287.         s += 2;
  288.         keycmd = getkeycmd(&s);
  289.     }
  290.  
  291.     if (keycmd == F_XKEY) {
  292.         if (*s == 0) {
  293.         xprintf("Bad function-key specification.\n");
  294.         xprintf("Null key not allowed\n");
  295.         return (-1);
  296.         }
  297.         *sp = s;
  298.         return (-2);
  299.     }
  300.  
  301.     if (s[1] != 0) {    /* if symbolic name */
  302.         char   *ts;
  303.  
  304.         ts = short2str(s);
  305.         if (!str7cmp(ts, "space") || !str7cmp(ts, "Spc"))
  306.         c = ' ';
  307.         else if (!str7cmp(ts, "return") || !str7cmp(ts, "Ret"))
  308.         c = '\r';
  309.         else if (!str7cmp(ts, "newline") || !str7cmp(ts, "Lfd"))
  310.         c = '\n';
  311.         else if (!str7cmp(ts, "linefeed"))
  312.         c = '\n';
  313.         else if (!str7cmp(ts, "tab"))
  314.         c = '\t';
  315.         else if (!str7cmp(ts, "escape") || !str7cmp(ts, "Esc"))
  316.         c = '\033';
  317.         else if (!str7cmp(ts, "backspace"))
  318.         c = '\b';
  319.         else if (!str7cmp(ts, "delete"))
  320.         c = '\177';
  321.         else {
  322.         xprintf("bad key specification -- unknown name \"%s\"\n", s);
  323.         return -1;    /* error */
  324.         }
  325.     }
  326.     else
  327.         c = *s;        /* just a single char */
  328.  
  329.     if (control)
  330.         c = tocontrol(c);
  331.     if (meta)
  332.         c |= META;
  333.     if (ctrlx)
  334.         c |= 0400;
  335.     }
  336.     return (c & 0777);
  337. }
  338.  
  339.  
  340. /*ARGSUSED*/
  341. void
  342. dobindkey(v, c)
  343.     Char  **v;
  344.     struct command *c;
  345. {
  346.     KEYCMD *map;
  347.     int     string, no, remove;
  348.     Char   *par;
  349.     Char    p;
  350.     Char    inbuf[200];
  351.     Char    outbuf[200];
  352.     Char   *in;
  353.     Char   *out;
  354.     KEYCMD  cmd;
  355.  
  356.     if (!MapsAreInited)
  357.     ed_InitMaps();
  358.  
  359.     map = CcKeyMap;
  360.     string = 0;
  361.     remove = 0;
  362.     for (no = 1, par = v[no]; 
  363.      par != NULL && (*par++ & CHAR) == '-'; no++, par = v[no]) {
  364.     if ((p = (*par & CHAR)) == '-') {
  365.         break;
  366.     }
  367.     else if (p == 'a') {
  368.         map = CcAltMap;
  369.     }
  370.     else if (p == 's') {
  371.         string = 1;
  372.     }
  373.     else if (p == 'r') {
  374.         remove = 1;
  375.     }
  376.     else if (p == 'v') {
  377.         ed_InitVIMaps();
  378.         return;
  379.     }
  380.     else if (p == 'e') {
  381.         ed_InitEmacsMaps();
  382.         return;
  383.     }
  384.     else if (p == 'd') {
  385. #ifdef VIDEFAULT
  386.         ed_InitVIMaps();
  387. #else
  388.         ed_InitEmacsMaps();
  389. #endif
  390.         return;
  391.     }
  392.     else if (p == 'l') {
  393.         list_functions();
  394.         return;
  395.     }
  396.     else {
  397.         bindkey_usage();
  398.         return;
  399.     }
  400.     }
  401.  
  402.     if (!v[no]) {
  403.     print_all_keys();
  404.     return;
  405.     }
  406.  
  407.     if ((in = parsestring(v[no++], inbuf)) == NULL)
  408.     return;
  409.     if (remove) {
  410.     if (in[1]) {
  411.         (void) DeleteXkey(in);
  412.     }
  413.     else if (map[(unsigned char) *in] == F_XKEY) {
  414.         (void) DeleteXkey(in);
  415.         map[(unsigned char) *in] = F_UNASSIGNED;
  416.     }
  417.     else {
  418.         map[(unsigned char) *in] = F_UNASSIGNED;
  419.     }
  420.     return;
  421.     }
  422.     if (!v[no]) {
  423.     printkey(map, in);
  424.     return;
  425.     }
  426.     if (v[no + 1]) {
  427.     bindkey_usage();
  428.     return;
  429.     }
  430.     if (string) {
  431.     if ((out = parsestring(v[no], outbuf)) == NULL)
  432.         return;
  433.     AddXkey(in, out);
  434.     map[(unsigned char) *in] = F_XKEY;
  435.     }
  436.     else {
  437.     if ((cmd = parsecmd(v[no])) == 0)
  438.         return;
  439.     if (in[1]) {
  440.         AddXkeyCmd(in, (Char) cmd);
  441.         map[(unsigned char) *in] = F_XKEY;
  442.     }
  443.     else {
  444.         (void) ClearXkey(map, in);
  445.         map[(unsigned char) *in] = cmd;
  446.     }
  447.     }
  448. }
  449.  
  450. static void
  451. printkey(map, in)
  452.     KEYCMD *map;
  453.     Char   *in;
  454. {
  455.     unsigned char outbuf[100];
  456.     register struct KeyFuncs *fp;
  457.  
  458.     if (in[0] == 0 || in[1] == 0) {
  459.     (void) unparsestring(in, outbuf);
  460.     for (fp = FuncNames; fp->name; fp++) {
  461.         if (fp->func == map[(unsigned char) *in]) {
  462.         xprintf("%s\t->\t%s\n", outbuf, fp->name);
  463.         }
  464.     }
  465.     }
  466.     else {
  467.     (void) PrintXkey(in);
  468.     }
  469. }
  470.  
  471. static  KEYCMD
  472. parsecmd(str)
  473.     Char   *str;
  474. {
  475.     register struct KeyFuncs *fp;
  476.  
  477.     for (fp = FuncNames; fp->name; fp++) {
  478.     if (str7cmp(short2str(str), fp->name) == 0) {
  479.         return fp->func;
  480.     }
  481.     }
  482.     xprintf("Bad command name: %s\n", short2str(str));
  483.     return 0;
  484. }
  485.  
  486. int
  487. parseescape(ptr)
  488.     Char  **ptr;
  489. {
  490.     Char   *p, c;
  491.  
  492.     p = *ptr;
  493.  
  494.     if ((p[1] & CHAR) == 0) {
  495.     xprintf("Something must follow: %c\\n", *p);
  496.     return 0;
  497.     }
  498.     if ((*p & CHAR) == '\\') {
  499.     p++;
  500.     switch (*p & CHAR) {
  501.     case 'a':
  502.         c = '\007';        /* Bell */
  503.         break;
  504.     case 'b':
  505.         c = '\010';        /* Backspace */
  506.         break;
  507.     case 't':
  508.         c = '\011';        /* Horizontal Tab */
  509.         break;
  510.     case 'n':
  511.         c = '\012';        /* New Line */
  512.         break;
  513.     case 'v':
  514.         c = '\013';        /* Vertical Tab */
  515.         break;
  516.     case 'f':
  517.         c = '\014';        /* Form Feed */
  518.         break;
  519.     case 'r':
  520.         c = '\015';        /* Carriage Return */
  521.         break;
  522.     case 'e':
  523.         c = '\033';        /* Escape */
  524.         break;
  525.     case '0':
  526.     case '1':
  527.     case '2':
  528.     case '3':
  529.     case '4':
  530.     case '5':
  531.     case '6':
  532.     case '7':
  533.         {
  534.         register int cnt, val, ch;
  535.  
  536.         for (cnt = 0, val = 0; cnt < 3; cnt++) {
  537.             ch = *p++ & CHAR;
  538.             if (ch < '0' || ch > '7') {
  539.             p--;
  540.             break;
  541.             }
  542.             val = (val << 3) | (ch - '0');
  543.         }
  544.         if ((val & 0xffffff00) != 0) {
  545.             xprintf("Octal constant does not fit in a char.\n");
  546.             return 0;
  547.         }
  548.         c = val;
  549.         --p;
  550.         }
  551.         break;
  552.     default:
  553.         c = *p;
  554.         break;
  555.     }
  556.     }
  557.     else if ((*p & CHAR) == '^') {
  558.     p++;
  559.     c = (*p == '?') ? '\177' : ((*p & CHAR) & 0237);
  560.     }
  561.     else
  562.     c = *p;
  563.     *ptr = p;
  564.     return (c);
  565. }
  566.  
  567. static Char *
  568. parsestring(str, buf)
  569.     Char   *str;
  570.     Char   *buf;
  571. {
  572.     Char   *b;
  573.     Char   *p;
  574.  
  575.     b = buf;
  576.     if (*str == 0) {
  577.     xprintf("Null string specification\n");
  578.     return 0;
  579.     }
  580.  
  581.     for (p = str; *p != 0; p++) {
  582.     if ((*p & CHAR) == '\\' || (*p & CHAR) == '^') {
  583.         if ((*b++ = parseescape(&p)) == 0)
  584.         return 0;
  585.     }
  586.     else {
  587.         *b++ = *p & CHAR;
  588.     }
  589.     }
  590.     *b = 0;
  591.     return buf;
  592. }
  593.  
  594. unsigned char *
  595. unparsestring(str, buf)
  596.     Char   *str;
  597.     unsigned char *buf;
  598. {
  599.     unsigned char *b;
  600.     Char   *p;
  601.  
  602.     b = buf;
  603.     *b++ = '"';
  604.     if (*str == 0) {
  605.     *b++ = '^';
  606.     *b++ = '@';
  607.     *b++ = '"';
  608.     *b++ = 0;
  609.     return buf;
  610.     }
  611.  
  612.     for (p = str; *p != 0; p++) {
  613.     if (Iscntrl(*p)) {
  614.         *b++ = '^';
  615.         if (*p == '\177')
  616.         *b++ = '?';
  617.         else
  618.         *b++ = *p | 0100;
  619.     }
  620.     else if (*p == '^' || *p == '\\') {
  621.         *b++ = '\\';
  622.         *b++ = *p;
  623.     }
  624.     else if (*p == ' ' || (Isprint(*p) && !Isspace(*p))) {
  625.         *b++ = *p;
  626.     }
  627.     else {
  628.         *b++ = '\\';
  629.         *b++ = ((*p >> 6) & 7) + '0';
  630.         *b++ = ((*p >> 3) & 7) + '0';
  631.         *b++ = (*p & 7) + '0';
  632.     }
  633.     }
  634.     *b++ = '"';
  635.     *b++ = 0;
  636.     return buf;            /* should check for overflow */
  637. }
  638.  
  639. static void
  640. print_all_keys()
  641. {
  642.     int     prev, i;
  643.  
  644.     xprintf("Standard key bindings\n");
  645.     prev = 0;
  646.     for (i = 0; i < 256; i++) {
  647.     if (CcKeyMap[prev] == CcKeyMap[i])
  648.         continue;
  649.     printkeys(CcKeyMap, prev, i - 1);
  650.     prev = i;
  651.     }
  652.     printkeys(CcKeyMap, prev, i - 1);
  653.  
  654.     xprintf("Alternative key bindings\n");
  655.     prev = 0;
  656.     for (i = 0; i < 256; i++) {
  657.     if (CcAltMap[prev] == CcAltMap[i])
  658.         continue;
  659.     printkeys(CcAltMap, prev, i - 1);
  660.     prev = i;
  661.     }
  662.     printkeys(CcAltMap, prev, i - 1);
  663.     xprintf("Multi-character bindings\n");
  664.     (void) PrintXkey(STRNULL);    /* print all Xkey bindings */
  665. }
  666.  
  667. static void
  668. printkeys(map, first, last)
  669.     KEYCMD *map;
  670.     int     first, last;
  671. {
  672.     register struct KeyFuncs *fp;
  673.     Char    firstbuf[2], lastbuf[2];
  674.     unsigned char unparsbuf[10], extrabuf[10];
  675.  
  676.     firstbuf[0] = first;
  677.     firstbuf[1] = 0;
  678.     lastbuf[0] = last;
  679.     lastbuf[1] = 0;
  680.     if (map[first] == F_UNASSIGNED) {
  681.     if (first == last)
  682.         xprintf("%-15s->  is undefined\n",
  683.             unparsestring(firstbuf, unparsbuf));
  684.     return;
  685.     }
  686.  
  687.     for (fp = FuncNames; fp->name; fp++) {
  688.     if (fp->func == map[first]) {
  689.         if (first == last) {
  690.         xprintf("%-15s->  %s\n",
  691.             unparsestring(firstbuf, unparsbuf), fp->name);
  692.         }
  693.         else {
  694.         xprintf("%-4s to %-7s->  %s\n",
  695.             unparsestring(firstbuf, unparsbuf),
  696.             unparsestring(lastbuf, extrabuf), fp->name);
  697.         }
  698.         return;
  699.     }
  700.     }
  701.     if (map == CcKeyMap) {
  702.     xprintf("BUG!!! %s isn't bound to anything.\n",
  703.         unparsestring(firstbuf, unparsbuf));
  704.     xprintf("CcKeyMap[%d] == %d\n", first, CcKeyMap[first]);
  705.     }
  706.     else {
  707.     xprintf("BUG!!! %s isn't bound to anything.\n",
  708.         unparsestring(firstbuf, unparsbuf));
  709.     xprintf("CcAltMap[%d] == %d\n", first, CcAltMap[first]);
  710.     }
  711. }
  712.  
  713. static void
  714. bindkey_usage()
  715. {
  716.     xprintf(
  717.     "Usage: bindkey [options] [--] [in-string [out-string | command]]\n");
  718.     xprintf("    -a   bind key in alternative key binding\n");
  719.     xprintf("    -s   bind an out-string instad of a command\n");
  720.     xprintf("    -v   initialized maps to default vi bindings\n");
  721.     xprintf("    -e   initialized maps to default emacs bindings\n");
  722.     xprintf("    -d   initialized maps to default bindings\n");
  723.     xprintf("    -l   list available functions with descriptions\n");
  724.     xprintf("    -r   remove the binding of in-string\n");
  725.     xprintf(
  726.        "\nIn no out-string or command is given, the binding for in-string\n");
  727.     xprintf("is printed or all bindings if in-strings is not given.\n");
  728. }
  729.  
  730. static void
  731. list_functions()
  732. {
  733.     register struct KeyFuncs *fp;
  734.  
  735.     for (fp = FuncNames; fp->name; fp++) {
  736.     xprintf("%s\n          %s\n", fp->name, fp->description);
  737.     }
  738. }
  739.  
  740. /*ARGSUSED*/
  741. void
  742. dobind(v, dummy)
  743.     register Char **v;
  744.     struct command *dummy;
  745. {
  746.     register int c;
  747.     register struct KeyFuncs *fp;
  748.     register int i, prev;
  749.     Char   *p, *l;
  750.     Char    buf[1000];
  751.  
  752.     /*
  753.      * Assume at this point that i'm given 2 or 3 args - 'bind', the f-name,
  754.      * and the key; or 'bind' key to print the func for that key.
  755.      */
  756.  
  757.     if (!MapsAreInited)
  758.     ed_InitMaps();
  759.  
  760.     if (v[1] && v[2] && v[3]) {
  761.     xprintf(
  762.        "usage: bind [KEY | COMMAND KEY | \"emacs\" | \"vi\" | \"-a\"]\n");
  763.     return;
  764.     }
  765.  
  766.     if (v[1] && v[2]) {        /* if bind FUNCTION KEY */
  767.     for (fp = FuncNames; fp->name; fp++) {
  768.         if (str7cmp(short2str(v[1]), fp->name) == 0) {
  769.         Char   *s = v[2];
  770.  
  771.         if ((c = parsekey(&s)) == -1)
  772.             return;
  773.         if (c == -2) {    /* extented key */
  774.             for (i = 0; i < 256; i++) {
  775.             if (i != 033 && (CcKeyMap[i] == F_XKEY ||
  776.                      CcAltMap[i] == F_XKEY)) {
  777.                 p = buf;
  778.                 if (i > 0177) {
  779.                 *p++ = 033;
  780.                 *p++ = i & ASCII;
  781.                 }
  782.                 else {
  783.                 *p++ = i;
  784.                 }
  785.                 for (l = s; *l != 0; l++) {
  786.                 *p++ = *l;
  787.                 }
  788.                 *p = 0;
  789.                 AddXkeyCmd(buf, fp->func);
  790.             }
  791.             }
  792.             return;
  793.         }
  794.         if (c & 0400) {
  795.             if (VImode) {
  796.             CcAltMap[c & 0377] = fp->func;    
  797.             /* bind the vi cmd mode key */
  798.             if (c & META) {
  799.                 buf[0] = 033;
  800.                 buf[1] = c & ASCII;
  801.                 buf[2] = 0;
  802.                 AddXkeyCmd(buf, fp->func);
  803.             }
  804.             }
  805.             else {
  806.             buf[0] = 030;    /* ^X */
  807.             buf[1] = c & 0377;
  808.             buf[2] = 0;
  809.             AddXkeyCmd(buf, fp->func);
  810.             CcKeyMap[030] = F_XKEY;
  811.             }
  812.         }
  813.         else {
  814.             CcKeyMap[c] = fp->func;    /* bind the key */
  815.             if (c & META) {
  816.             buf[0] = 033;
  817.             buf[1] = c & ASCII;
  818.             buf[2] = 0;
  819.             AddXkeyCmd(buf, fp->func);
  820.             }
  821.         }
  822.         return;
  823.         }
  824.     }
  825.     stderror(ERR_NAME | ERR_STRING, "Invalid function");
  826.     }
  827.     else if (v[1]) {
  828.     char   *cv = short2str(v[1]);
  829.  
  830.     if (str7cmp(cv, "list") == 0) {
  831.         for (fp = FuncNames; fp->name; fp++) {
  832.         xprintf("%s\n", fp->name);
  833.         }
  834.         return;
  835.     }
  836.     if ((str7cmp(cv, "emacs") == 0) ||
  837. #ifndef VIDEFAULT
  838.         (str7cmp(cv, "defaults") == 0) ||
  839.         (str7cmp(cv, "default") == 0) ||
  840. #endif
  841.         (str7cmp(cv, "mg") == 0) ||
  842.         (str7cmp(cv, "gnumacs") == 0)) {
  843.         /* reset keys to default */
  844.         ed_InitEmacsMaps();
  845. #ifdef VIDEFAULT
  846.     }
  847.     else if ((str7cmp(cv, "vi") == 0)
  848.          || (str7cmp(cv, "default") == 0)
  849.          || (str7cmp(cv, "defaults") == 0)) {
  850. #else
  851.     }
  852.     else if (str7cmp(cv, "vi") == 0) {
  853. #endif
  854.         ed_InitVIMaps();
  855.     }
  856.     else {            /* want to know what this key does */
  857.         Char   *s = v[1];
  858.  
  859.         if ((c = parsekey(&s)) == -1)
  860.         return;
  861.         if (c == -2) {    /* extended key */
  862.         (void) PrintXkey(s);
  863.         return;
  864.         }
  865.         pkeys(c, c);    /* must be regular key */
  866.     }
  867.     }
  868.     else {            /* list all the bindings */
  869.     prev = 0;
  870.     for (i = 0; i < 256; i++) {
  871.         if (CcKeyMap[prev] == CcKeyMap[i])
  872.         continue;
  873.         pkeys(prev, i - 1);
  874.         prev = i;
  875.     }
  876.     pkeys(prev, i - 1);
  877.     prev = 0;
  878.     for (i = 256; i < 512; i++) {
  879.         if (CcAltMap[prev & 0377] == CcAltMap[i & 0377])
  880.         continue;
  881.         pkeys(prev, i - 1);
  882.         prev = i;
  883.     }
  884.     pkeys(prev, i - 1);
  885.     (void) PrintXkey(STRNULL);    /* print all Xkey bindings */
  886.     }
  887.     return;
  888. }
  889.  
  890. static void
  891. pkeys(first, last)
  892.     register int first, last;
  893. {
  894.     register struct KeyFuncs *fp;
  895.     register KEYCMD *map;
  896.     char    buf[8];
  897.  
  898.     if (last & 0400) {
  899.     map = CcAltMap;
  900.     first &= 0377;
  901.     last &= 0377;
  902.     }
  903.     else {
  904.     map = CcKeyMap;
  905.     }
  906.     if (map[first] == F_UNASSIGNED) {
  907.     if (first == last)
  908. #ifdef _SEQUENT_
  909.         xprintf(" %s\t\tis undefined\n",
  910.             unparsekey(map == CcAltMap ? first | 0400 : first));
  911. #else                /* _SEQUENT_ */
  912.         xprintf(" %s\t\tis undefined\n", unparsekey(first));
  913. #endif                /* _SEQUENT_ */
  914.     return;
  915.     }
  916.  
  917.     for (fp = FuncNames; fp->name; fp++) {
  918.     if (fp->func == map[first]) {
  919.         if (first == last) {
  920.         xprintf(" %s\t\t%s\n",
  921.             unparsekey((first & 0377) | (map == CcAltMap ? 0400 : 0)),
  922.             fp->name);
  923.         }
  924.         else {
  925.         (void) strcpy(buf, unparsekey((first & 0377) |
  926.                           (map == CcAltMap ? 0400 : 0)));
  927.         xprintf(" %s..%s\t\t%s\n", buf,
  928.              unparsekey((last & 0377) | (map == CcAltMap ? 0400 : 0)),
  929.             fp->name);
  930.         }
  931.         return;
  932.     }
  933.     }
  934.     if (map == CcKeyMap) {
  935.     xprintf("BUG!!! %s isn't bound to anything.\n", unparsekey(first));
  936.     xprintf("CcKeyMap[%d] == %d\n", first, CcKeyMap[first]);
  937.     }
  938.     else {
  939.     xprintf("BUG!!! %s isn't bound to anything.\n",
  940.         unparsekey(first & 0400));
  941.     xprintf("CcAltMap[%d] == %d\n", first, CcAltMap[first]);
  942.     }
  943. }
  944.